package com.basic.ui.view

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams
import android.widget.*
import androidx.appcompat.widget.AppCompatImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.basic.ui.R
import java.util.concurrent.atomic.AtomicInteger

/**
 * 减少布局文件的使用, 便于在代码中快速创建view, 使用和test查看[com.basic.ui.TestNolayout]
 *
 * @author Peter Liu
 * @since 2023/7/19 22:08
 *
 */

fun <T : ViewGroup, R : View> T.add(view: R): R {
    var id = view.id
    if (id <= 0) {
        id = gNextId()
        view.id = id
    }
    //避免重复添加view
    val cache = this.getTag(id)
    if (cache == null) {
        this.setTag(id, view)
        addView(view)
    }
    return view
}

fun ViewGroup.gNextId(): Int {
    var genId = this.getTag(R.id.gIds) as? AtomicInteger
    if (genId == null) {
        genId = AtomicInteger(1)
        setTag(R.id.gIds, genId)
    }
    val result = genId.get()
    genId.compareAndSet(result, result + 1)
    return result
}

fun ViewGroup.gNextId(key: String): Int {
    return this.id.coerceAtLeast(1).shl(12).and(key.hashCode())
}

inline fun TextView(
    context: Context,
    attrs: AttributeSet? = null,
    crossinline initFun: TextView.() -> Unit,
): TextView {
    return context.createView(attrs, initFun = initFun)
}

inline fun <T : ViewGroup> T.TextView(
    attrs: AttributeSet? = null,
    crossinline initFun: TextView.() -> Unit
): TextView {
    return add(TextView(this.context, attrs, initFun = initFun))
}

inline fun ImageView(
    context: Context,
    attrs: AttributeSet? = null,
    crossinline initFun: AppCompatImageView.() -> Unit,
): ImageView {
    return context.createView(attrs, initFun = initFun)
}

inline fun <T : ViewGroup> T.ImageView(
    attrs: AttributeSet? = null,
    crossinline initFun: ImageView.() -> Unit
): ImageView {
    return add(ImageView(this.context, attrs, initFun = initFun))
}

inline fun Button(
    context: Context,
    attrs: AttributeSet? = null,
    crossinline initFun: Button.() -> Unit,
): Button {
    return context.createView(attrs, initFun = initFun)
}

inline fun <T : ViewGroup> T.Button(
    attrs: AttributeSet? = null,
    crossinline initFun: Button.() -> Unit
): Button {
    return add(Button(this.context, attrs, initFun = initFun))
}

inline fun LinearLayout(
    context: Context,
    attrs: AttributeSet? = null,
    crossinline initFun: LinearLayout.() -> Unit,
): LinearLayout {
    return context.createView(attrs, initFun)
}

inline fun LinearLayout.Params(initFun: LinearLayout.LayoutParams.() -> Unit): LinearLayout.LayoutParams {
    return LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
        .also {
            initFun(it)
        }
}

inline fun <T : ViewGroup> T.LinearLayout(
    attrs: AttributeSet? = null,
    crossinline initFun: LinearLayout.() -> Unit
): LinearLayout {
    return add(LinearLayout(this.context, attrs, initFun = initFun))
}

inline fun RelativeLayout(
    context: Context,
    attrs: AttributeSet? = null,
    crossinline initFun: RelativeLayout.() -> Unit,
): RelativeLayout {
    return context.createView(attrs, initFun)
}

inline fun RelativeLayout.Params(initFun: RelativeLayout.LayoutParams.() -> Unit): RelativeLayout.LayoutParams {
    return RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
        .also {
            initFun(it)
        }
}

inline fun <T : ViewGroup> T.RelativeLayout(
    attrs: AttributeSet? = null,
    crossinline initFun: RelativeLayout.() -> Unit
): RelativeLayout {
    return add(RelativeLayout(this.context, attrs, initFun = initFun))
}

inline fun FrameLayout(
    context: Context,
    attrs: AttributeSet? = null,
    crossinline initFun: FrameLayout.() -> Unit,
): FrameLayout {
    return context.createView(attrs, initFun)
}

inline fun FrameLayout.Params(initFun: FrameLayout.LayoutParams.() -> Unit): FrameLayout.LayoutParams {
    return FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
        .also {
            initFun(it)
        }
}

inline fun <T : ViewGroup> T.FrameLayout(
    attrs: AttributeSet? = null,
    crossinline initFun: FrameLayout.() -> Unit
): FrameLayout {
    return add(FrameLayout(this.context, attrs, initFun = initFun))
}

inline fun RecyclerView(
    context: Context,
    attrs: AttributeSet? = null,
    crossinline initFun: RecyclerView.() -> Unit,
): RecyclerView {
    return context.createView(attrs, initFun)
}

inline fun <T : ViewGroup> T.RecyclerView(
    attrs: AttributeSet? = null,
    crossinline initFun: RecyclerView.() -> Unit
): RecyclerView {
    return add(RecyclerView(this.context, attrs, initFun = initFun))
}

inline fun ViewPager2(
    context: Context,
    attrs: AttributeSet? = null,
    crossinline initFun: ViewPager2.() -> Unit,
): ViewPager2 {
    return context.createView(attrs, initFun)
}

inline fun <T : ViewGroup> T.ViewPager2(
    attrs: AttributeSet? = null,
    crossinline initFun: ViewPager2.() -> Unit
): ViewPager2 {
    return add(ViewPager2(this.context, attrs, initFun = initFun))
}


inline fun ConstraintLayout(
    context: Context,
    attrs: AttributeSet? = null,
    crossinline initFun: ConstraintLayout.() -> Unit,
): ConstraintLayout {
    return context.createView(attrs, initFun)
}

inline fun ConstraintLayout.Params(initFun: ConstraintLayout.LayoutParams.() -> Unit): ConstraintLayout.LayoutParams {
    return ConstraintLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
        .also {
            initFun(it)
        }
}

inline fun <T : ViewGroup> T.ConstraintLayout(
    attrs: AttributeSet? = null,
    crossinline initFun: ConstraintLayout.() -> Unit
): ConstraintLayout {
    return add(ConstraintLayout(this.context, attrs, initFun = initFun))
}